package org.glavo.bot.data

import kotlinx.serialization.json.*
import kotlin.system.exitProcess

@Suppress("EXPERIMENTAL_API_USAGE")
data class Player(
    val qq: Long,
    val names: List<String>,
    val nicknames: List<String>,
    val permissions: Permissions = Permission.Default
) {
    companion object {
        private fun readPlayers() =
            Json.parseToJsonElement(Data.readResourceAsText("secret/PlayerList.json"))
                .jsonArray
                .map { e ->
                    val obj = e.jsonObject

                    val qq = obj["qq"]!!.jsonPrimitive.long
                    val names = obj["names"]?.jsonArray?.map { it.jsonPrimitive.content } ?: emptyList()
                    val nicknames = obj["nicknames"]?.jsonArray?.map { it.jsonPrimitive.content } ?: emptyList()
                    val permissions = run {
                        when (val p = obj["permission"]) {
                            null -> {
                                Permission.Default
                            }
                            is JsonPrimitive -> {
                                Permission.ofLevel(p.content)
                            }
                            is JsonObject -> {
                                Permission.ofLevel(p["level"]?.jsonPrimitive?.content) //TODO
                            }
                            else -> {
                                System.err.println("错误的权限格式: $p")
                                exitProcess(-1)
                            }
                        }
                    }

                    Player(qq, names, nicknames, permissions)
                }.sortedBy { it.qq }

        fun reload() {
            All = readPlayers()
        }

        @Volatile
        var All: List<Player> = readPlayers()
            private set

        val Glavo: Player
            get() = All.first { it.qq == 360736041L }

        operator fun get(qq: Long): Player? {
            return All.binarySearchBy(qq) { it.qq }.let { if (it >= 0) All[it] else null }
        }

        fun search(name: String): Player? {
            Player.All.firstOrNull { it.names.any { theName -> name.equals(theName, ignoreCase = true) } }?.let {
                return it
            }
            Player.All.firstOrNull { it.nicknames.any { theName -> name.equals(theName, ignoreCase = true) } }?.let {
                return it
            }
            name.toLongOrNull()?.let { qq ->
                Player.All.firstOrNull { it.qq == qq }?.let {
                    return it
                }
            }
            return null
        }

        fun nameOf(qq: Long): String? {
            return get(qq)?.names?.firstOrNull()
        }
    }

}
